﻿using System;
using System.Configuration;
using System.Linq;
using System.Net.Configuration;
using System.Net.Mail;
using System.Transactions;
using System.Web;
using System.Web.Configuration;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using InnovaApp.Layers.DataLayer;
using InnovaApp.Layers.DomainLayer;
using InnovaApp.Layers.ResourcesLayer.Properties;
using InnovaApp.Layers.SecurityLayer.Models.AccountModels;
using InnovaApp.Layers.SecurityLayer.Models.AccountModels.MembershipServices;
using INNOVACALL.Framework.Common;
using INNOVACALL.Framework.Common.Extensions;
using System.Net;

namespace InnovaApp.Layers.SecurityLayer.Controllers
{
    public class RegisterController : _Controllers_Base<RegisterModel>
    {
        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        /// <summary>
        /// Initializes data that might not be available when the constructor is called.
        /// </summary>
        /// <param name="requestContext">The HTTP context and route data.</param>
        protected override void Initialize(RequestContext requestContext)
        {
            base.eMethodBase = "InnovaApp.Layers.SecurityLayer.Controllers.RegisterController";
            base.specificCssCollection = new string[] { "_FormCommon.css", "Views/Account/AccountCommon.css" };
            base.specificJSCollection = null;
            base.dynamicJSCollection = null;
            base.specificJqueryJSCollection = new string[] { "InnovacallJS/Register/Register.js" };
            base.externalCSS = null;
            base.Meta.Add(enMeta.Description, Resources.View_Register_Meta_Description);
            base.Meta.Add(enMeta.Keywords, Resources.View_Register_Meta_Keywords);
            base.Meta.Add(enMeta.Subject, Resources.View_Register_Meta_Subject);

            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        #region Register

        /// <summary>
        /// URL[Get]: /Register
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous, HttpGet]
        public ActionResult Index()
        {
            using (DataRepositories _dataContext = new DataRepositories())
            {
                base.InitView(
                    Resources.View_Register_PageTitle,
                    string.Empty,
                    specificCssCollection,
                    specificJSCollection,
                    dynamicJSCollection,
                    specificJqueryJSCollection,
                    jsVariables,
                    externalCSS,
                    Meta,
                    _dataContext,
                    false
                    );
            }
            return View(ContentData);
        }

        /// <summary>
        /// URL[Post]: /Register
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Index(RegisterModel model)
        {
            string Message = string.Empty;
            bool MailSent = false;
            SendActivationEmailParameters sendActivationEmailParameters = new SendActivationEmailParameters();
            object eParameters = new { @model_Username = model.UserToRegister.Username };
            var currentMembershipAppName = Membership.ApplicationName;
            var currentRolesAppName = Roles.ApplicationName;
            //Création du compte utilisateur
            MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserToRegister.Username, model.UserToRegister.Password, model.UserToRegister.Email);
            if (createStatus == MembershipCreateStatus.Success)
            {
                using (TransactionScope _ts = new TransactionScope())
                {
                    try
                    {
                        using (DataRepositories _dataContext = new DataRepositories())
                        {
                            InnoAppUser currentUser = _dataContext.InnoAppUser_Rep.Query(x => x.InnoApplication.Name == currentMembershipAppName && x.Username == model.UserToRegister.Username).FirstOrDefault();
                            if (currentUser == null) throw new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethodBase + "Index[Post]", eParameters, Resources.ErrMsg_NewCreatedUserNotFound);
                            currentUser.Comment = model.UserToRegister.Comment;
                            //currentUser.CreationDate (déjà enregistré)
                            currentUser.Email = model.UserToRegister.Email;
                            currentUser.FailedPasswordAnswerAttemptCount = 0;
                            currentUser.FailedPasswordAnswerAttemptWindowStart = null;
                            currentUser.FailedPasswordAttemptCount = 0;
                            currentUser.FailedPasswordAttemptWindowStart = null;
                            _dataContext.Save();
                            sendActivationEmailParameters.userEMail = currentUser.Email;
                            sendActivationEmailParameters.userCreationDate = currentUser.CreationDate.ToString();
                            sendActivationEmailParameters.username = currentUser.Username;
                        }
                        _ts.Complete();
                        Message += "Transaction complete, user created but not activated\n";
                        Message += "Activation mail preparation starts\n";
                        MailSent = SendActivationEmail(sendActivationEmailParameters, ref Message);
                        //return RedirectToAction("SendActivationEmail", new { username = model.UserToRegister.Username });
                    }
                    catch (Exception ex)
                    {
                        _ts.Dispose();
                        return Json(new { @success = MailSent, @message = Message, @ScriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_ErrorDuringTransaction_Title.Replace("'", "\\'") + "','" + Resources.View_Register_ErrorDuringTransaction_Message.Replace("'", "\\'") + "');" });
                    }

                }
            }
            else
            {
                string FailureReason = base.ErrorCodeToString(createStatus);
                return Json(new { @success = MailSent, @message = Message, @ScriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_ErrorDuringTransaction_Title.Replace("'", "\\'") + "','" + FailureReason.Replace("'", "\\'") + "');" });
            }
            return Json(new { @success = MailSent, @message = Message, @ScriptToExecute = "$.fn.jqDialogAlert('" + Resources.View_Register_Success_Title.Replace("'", "\\'") + "','" + Resources.View_Register_Success_Message.Replace("'", "\\'") + "','/LogOn');" });
        }

        private class SendActivationEmailParameters
        {
            public string userEMail;
            public string userCreationDate;
            public string username;
        }

        /// <summary>
        /// Activation EMail sender
        /// </summary>
        /// <param name="sendActivationEmailParameters"></param>
        private bool SendActivationEmail(SendActivationEmailParameters sendActivationEmailParameters, ref string logMessage)
        {
            bool toReturn = true;
            object eMethodParameters = new { @userEMail = sendActivationEmailParameters.userEMail, @userCreationDate = sendActivationEmailParameters.userCreationDate, @username = sendActivationEmailParameters.username };
            Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Request.ApplicationPath);
            MailSettingsSectionGroup settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");

            string SiteBaseUrl = ConfigurationManager.AppSettings["SiteBaseUrl"];
            string landingPageAddress = string.Format(@"http://{0}", SiteBaseUrl);
            string cryptedPart = string.Format("{0}{1}", sendActivationEmailParameters.userEMail, sendActivationEmailParameters.userCreationDate);
            cryptedPart = cryptedPart.EncodeSHA1();
            landingPageAddress = string.Format(@"{0}/AccountActivation?codeactivation={1}&email={2}", landingPageAddress, Server.UrlEncode(cryptedPart), Server.UrlEncode(sendActivationEmailParameters.userEMail));
            try
            {
                MailAddress from = new MailAddress(ConfigurationManager.AppSettings["AccountActivationFromMailAddress"], ConfigurationManager.AppSettings["SiteBaseUrl"]);
                MailAddress to = new MailAddress(sendActivationEmailParameters.userEMail, sendActivationEmailParameters.username);

                MailMessage message = new MailMessage(from, to);
                message.IsBodyHtml = true;

                message.Subject = string.Format(Resources.View_Register_RegistrationActivationMail_Subject, SiteBaseUrl);

                message.Body += Resources.View_Register_RegistrationActivationMail_Body1 + "\n<br/>";
                message.Body += "<a href=\"" + landingPageAddress + "\">" + Server.HtmlEncode(Resources.View_Register_ClickHereToRegister) + "</a><br/>";
                message.Body += Resources.View_Register_RegistrationActivationMail_Body2 + "\n<br/>";

                SmtpClient smtp = new SmtpClient();
                smtp.UseDefaultCredentials = settings.Smtp.Network.DefaultCredentials;
                smtp.Host = settings.Smtp.Network.Host;
                smtp.Port = settings.Smtp.Network.Port;
                smtp.EnableSsl = settings.Smtp.Network.EnableSsl;
                smtp.Credentials = new NetworkCredential(settings.Smtp.Network.UserName, settings.Smtp.Network.Password);
                smtp.Send(message);
                logMessage += "Activation mail sent\n";
            }
            catch (Exception ex)
            {
                logMessage += "The folowing error occurs : \n";
                logMessage += ex.Message;
                toReturn = false;
                return toReturn;
                //throw new INNOVACALL.Framework.Common.InnovacallExceptions.IdentificationException(eMethodBase + "SendActivationEmail", eMethodParameters, Resources.View_Register_RegistrationActivationMail_Failed);
            }
            return toReturn;
        }
        #endregion
    }
}
